package com.young.pattern.singletonPattern;

import com.sun.org.apache.regexp.internal.RE;

/**
 * 懒汉式单例模式:
 *  懒汉式单例模式的构造函数也是私有的.与恶汉式单例类不同的是,懒汉式单例类在第一次被引用时将自己实例化,
 *      在懒汉式单例类被加载时不会将自己实例化.
 */
public class LazySingleton {
    private volatile static LazySingleton instance = null;

    private LazySingleton(){};

    synchronized public static LazySingleton getInstance1() {
        if (instance == null) {
            instance = new LazySingleton();
        }
        return instance;
    }

    /**
     * 在上述懒汉式单例类中,在getInstance1()方法前面增加了关键字Synchronized进行线程锁定,以处理多个线程同时访问的问题.上述代码虽然解决了线程安全问题,但是每次调用
     * getInstance1方法都需要进行线程线程锁定判断,在多线程高并发访问环境中将会导致系统性能大大降低.因此优化到如下getInstance2:

     */

    public static LazySingleton getInstance2() {
        if (instance == null) {
            synchronized (LazySingleton.class){
                instance = new LazySingleton();
            }
        }
        return instance;
    }

    /**
     *
     * 使用如上来进行实现懒汉式单例模式,假如在某一瞬间线程A和线程B都在调用getInstance2()方法,此时instance对象为null值,就能通过null == instance的判断.由于实现了
     * synchronized加锁机制,线程A进入synchronized锁定的代码中执行实例创建代码,线程B处于等待状态,必须等待线程A执行完毕后才可以进入synchronized锁定的代码.
     * 但当A执行完毕时线程B并不知道实例已经被创建,将继续创建新的实例,导致产生多个单例对象,违背了单例模式的设计思想,因此需要更改为如下getInstance方法
     */

    public static LazySingleton getInstance(){
        if (instance == null){
            synchronized (LazySingleton.class){
                if (instance == null){
                    instance = new LazySingleton();
                }
            }
        }
        return instance;
    }

    /**
     * 即使使用双重检查锁定来实现懒汉式单例类,需要在静态成员变量instance之前增加修饰符volatile,被volatile修饰的成员变量可以确保多个线程都能够正确处理,
     * 且该代码只能在JDK5及以上版本中才能正常执行.由于volatile关键字会屏蔽Java虚拟机所做的一些代码优化,可能会导致系统的运行效率降低,因此即使使用双重
     * 检查锁定来实现单例模式也不是一种完美的实现方式.
     */

}
